#ifndef _MINIMIZER_
#define _MINIMIZER_

#include <stdio.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_min.h>
#include "Spline.h"

 double fn1 (double x, void * params)
    {
      CSpline<double> *sp=( CSpline<double> * )params;
      double val=(*sp).y(x);
      printf ("%g %g\n", x,val);
      return val;
      
    }
  
class CMinimizer
{
 public:
 
  CMinimizer(double *xsp, double *ysp, int Npsp, 
	     double a=0.0, double b=10.0, double m=0.5){
    
    CSpline<double> sp(xsp, ysp, Npsp, "linear ");
    int status;
    int iter = 0, max_iter = 100;
    const gsl_min_fminimizer_type *T;
    gsl_min_fminimizer *s;
    // double m = 2.0, m_expected = M_PI;
    //   double a = 0.0, b = 6.0;
       gsl_function F;
       
       F.function = &fn1;
       F.params = (void*)&sp;
       
       T = gsl_min_fminimizer_brent;
       s = gsl_min_fminimizer_alloc (T);
       gsl_min_fminimizer_set (s, &F, m, a, b);
       
       printf ("using %s method\n",
               gsl_min_fminimizer_name (s));
       
       /* printf ("%5s [%9s, %9s] %9s %10s %9s\n",
               "iter", "lower", "upper", "min",
               "err", "err(est)");*/
     
       printf ("%5d [%.7f, %.7f] %.7f %.7f\n",
               iter, a, b,
               m,  b - a);
     
       do
         {
           iter++;
           status = gsl_min_fminimizer_iterate (s);
     
           m = gsl_min_fminimizer_x_minimum (s);
           a = gsl_min_fminimizer_x_lower (s);
           b = gsl_min_fminimizer_x_upper (s);
     
           status 
             = gsl_min_test_interval (a, b, 0.001, 0.0);
     
           if (status == GSL_SUCCESS)
             printf ("Converged:\n");
     
           printf ("%5d [%.7f, %.7f] "
                   "%.7f  %.7f\n",
                   iter, a, b,
                   m,  b - a);
         }
       while (status == GSL_CONTINUE && iter < max_iter);
     
       gsl_min_fminimizer_free (s);
       
  }

    
};

#endif
